﻿
using SIG.Basic.Extensions;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Infrastructure.Logging;
using SIG.Model;
using SIG.Repository;
using SIG.Resources;
using SIG.Resources.Admin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace SIG.Service
{
    public class LinkService: EntityService<Link>, ILinkService
    {
      
        private readonly ILinkRepository _linkRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public LinkService(ILinkRepository linkRepository, ILoggingService loggingService, ICacheService cacheService)
            : base(linkRepository, cacheService, loggingService)
        {
         
            _linkRepository = linkRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }

        public async Task<IList<Link>> GetActiveElementsAync(CancellationToken cancellationToken = default(CancellationToken))
        {
            //get list
            var key = $"{EntityNames.Link}_List_Active";

            IList<Link> linklist;
            if (SettingsManager.Link.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    linklist = (IList<Link>)_cacheService.Get(key);

                }
                else
                {
                    var goods = await _linkRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.LinkCategory);
                    linklist = goods.ToList();
                    _cacheService.Set(key, linklist, SettingsManager.Link.CacheDuration);
                }
            }
            else
            {
                var goods = await _linkRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.LinkCategory);
                linklist = goods.ToList();
            }

            return linklist;

        }



        public Link GetLinkDetail(int id)
        {
            return _linkRepository.GetFirstOrDefault(m => m.Id == id, m => m.LinkCategory);
        }

        public List<Link> GetPagedActiveElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Link}_ListCount_Active_{keyword}_{categoryId}";

            var totalIQuery = _linkRepository.GetAllElements().Where(g => g.Active);
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Link.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Link.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Link}_List_Active_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Link> link;
            Expression<Func<Link, bool>> filter = g => g.Active;
            Expression<Func<Link, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Link, bool>> filterByCategory = g => g.CategoryId == categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Link.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    link = (List<Link>)_cacheService.Get(key);

                }
                else
                {
                    link = _linkRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.LinkCategory).ToList();
                    _cacheService.Set(key, link, SettingsManager.Link.CacheDuration);
                }
            }
            else
            {
                link = _linkRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.LinkCategory).ToList();
            }

            return link;

        }



        public List<Link> GetPagedElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Link}_ListCount_{keyword}_{categoryId}";

            var totalIQuery = _linkRepository.GetAllElements();
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Title.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Link.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Link.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Link}_List_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Link> links;
            Expression<Func<Link, bool>> filter = g => true;
            Expression<Func<Link, bool>> filterByKeyword = g => g.Title.Contains(keyword);
            Expression<Func<Link, bool>> filterByCategory = g => g.CategoryId == categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Link.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    links = (List<Link>)_cacheService.Get(key);
                }
                else
                {
                    links = _linkRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.LinkCategory).ToList();
                    _cacheService.Set(key, links, SettingsManager.Link.CacheDuration);
                }
            }
            else
            {
                links = _linkRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.LinkCategory).ToList();
            }

            return links;

        }




       
        public IEnumerable<Link> LatesterLinks(int count)
        {
            var key = $"{EntityNames.Link}s_Latester_{count}";

            if (!SettingsManager.Link.EnableCaching)
            {
                return _linkRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active,  false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Link>)_cacheService.Get(key);

            }

            var linkList = _linkRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active , false).ToList();
            _cacheService.Set(key, linkList, SettingsManager.Link.CacheDuration);


            return linkList;
        }
        public IEnumerable<Link> LatesterLinks(int count,int categoryId)
        {
            if (categoryId == 0)
                return LatesterLinks(count);

            var key = $"{EntityNames.Link}s_Latester_{count}_{categoryId}";
            if (!SettingsManager.Link.EnableCaching)
            {
                return _linkRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.CategoryId == categoryId, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Link>)_cacheService.Get(key);

            }

            var linkList = _linkRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active & p.CategoryId == categoryId, false).ToList();
            _cacheService.Set(key, linkList, SettingsManager.Link.CacheDuration);


            return linkList;
        }


    }
}
